#include "lab3_problem2.h"

#include <iostream>

#include "../p1/IterationMethods.h"

namespace Lab3
{
    namespace Problem2
    {
        void problem2()
        {
        	static const uint32_t maxIterations = 200;
        	static const double errorTolerance = 0.00006;

        	// Path of the files of matrices A, b1, b2 and initial x0
        	static const std::string filePathForA("lab3/p2/datos/A.txt");
        	static const std::string filePathForb1("lab3/p2/datos/b1.txt");
        	static const std::string filePathForb2("lab3/p2/datos/b2.txt");
        	static const std::string filePathForx0("lab3/p2/datos/initialX.txt");

        	// Resolve A * x = b1 using Jacobi method. 
        	uint32_t jacobiLastIteration = 0;
        	double jacobiFirstOrderNorm = 0.0;
        	static const uint32_t jacobiMatrixDimension = 6;
        	Utils::Matriz jacobiMatrix(jacobiMatrixDimension, 1);
        	NumericalAnalysis::IterationMethod(NumericalAnalysis::Method_Jacobi, jacobiMatrixDimension, filePathForA, 
        	                                   filePathForb1, filePathForx0, errorTolerance, 
        		                               maxIterations, jacobiLastIteration, jacobiFirstOrderNorm, jacobiMatrix);
        	
        	// Print results
        	std::cout << "Lab 3 - Problem 2:" << std::endl;
        	std::cout << "--- JACOBI METHOD --- " << std::endl;
        	std::cout << "Last iteration = " << jacobiLastIteration << std::endl;
        	std::cout << "First order norm = " << jacobiFirstOrderNorm << std::endl;
        	std::cout << "Matrix: " << std::endl; 
        	Utils::PrintMatrix(jacobiMatrix); 
        	std::cout << std::endl << std::endl;

        	// Resolve A * x = b2 using Gauss-Seidel method.
        	uint32_t gaussSeidelLastIteration = 0;
        	double gaussSeidelFirstOrderNorm = 0.0;
        	static const uint32_t gaussSeidelMatrixDimension = 6;
        	Utils::Matriz gaussSeidelMatrix(gaussSeidelMatrixDimension, 1);
        	NumericalAnalysis::IterationMethod(NumericalAnalysis::Method_GaussSeidel, gaussSeidelMatrixDimension, 
        	                                   filePathForA, filePathForb2, filePathForx0, errorTolerance,
        		                               maxIterations, gaussSeidelLastIteration, gaussSeidelFirstOrderNorm, gaussSeidelMatrix);
        	
        	// Print results
        	std::cout << "--- GAUSS-SEIDEL METHOD --- " << std::endl;
        	std::cout << "Last iteration = " << gaussSeidelLastIteration << std::endl;
        	std::cout << "First order norm = " << gaussSeidelFirstOrderNorm << std::endl;
        	std::cout << "Matrix: " << std::endl; 
        	Utils::PrintMatrix(gaussSeidelMatrix); 
        }
    }
}
